package com.kairos.motion
{
	import flash.display.MovieClip;
	
	import com.bourre.commands.MockASyncCommandListener;
	import com.bourre.log.PixlibDebug;
	import com.kairos.engine.MockRTBeacon;
	
	import flexunit.framework.TestCase;	

	public class MovieClipRTTest extends TestCase
	{
		[Embed(source="anim.swf",symbol="Animation")] 
			private var Animation : Class;
		[Embed(source="anim.swf",symbol="Animation2")] 
			private var Animation2 : Class;
		[Embed(source="anim.swf")] 
			private var AnimationWithScene : Class;	
		
		private var _mc : MovieClip;
		private var _mcrt : MockMovieClipRT;
		private var _oB : MockRTBeacon;
		
		public override function setUp() : void
		{
			_mc = new Animation();
			_mcrt = new MockMovieClipRT ( _mc );
			_oB = MockRTBeacon.getInstance();
			_oB.setStep( 25 );
			//PixlibDebug.isOn = false;
		}
		
		public override function tearDown() : void
		{
			_mcrt.stop();
		}
		
		public function testConstruct () : void 
		{
			assertNotNull ( "MovieClipRT constructor returns null", _mcrt );
			assertNotNull ( _mcrt + ".getMovieClip() return null after creation", _mcrt.getMovieClip() );
			assertEquals ( _mcrt + ".getFramerate() don't return the default value", 40, _mcrt.getFramerate() );
		}
		
		public function testRun () : void 
		{
			var n : Number = 0;
			
			_mcrt.setLooping( false );
			_mcrt.start();
			
			while( _mcrt.isRunning() ) 
			{
				_oB.onTick( null );
				
				n++;
			}
			
			assertFalse ( _mcrt + ".isRunning() haven't finish its run", _mcrt.isRunning() );	
			assertEquals ( _mcrt + " haven't realized the animation in the time", 19, n );		
		}
		
		public function testRunWithLocalSpeed () : void 
		{
			var n : Number = 0;
			
			_mcrt.setLocalSpeed( 2 );
			_mcrt.setLooping( false );
			_mcrt.start();
			
			while( _mcrt.isRunning() ) 
			{
				_oB.onTick( null );
				
				n++;
			}
			
			assertFalse ( _mcrt + ".isRunning() haven't finish its run", _mcrt.isRunning() );	
			assertEquals ( _mcrt + " haven't realized the animation in the time", 10, n );		
		}

		public function testLoopRun () : void 
		{
			var n : Number = 0;
			
			_oB.setStep( 600 );
			
			_mcrt.start();
			_oB.onTick( null );
			
			assertEquals( _mcrt + " failed to loop at the end of the animation", 5, _mc.currentFrame );	
			
			_mcrt.gotoAndPlay( 20 );
			_mcrt.reverse();
			n = 0;
			
			_oB.onTick( null );
			
			assertEquals( _mcrt + " failed to loop at the end of the animation", 16, _mc.currentFrame );	
		}
		
		public function testGapGreaterThanAnimation () : void
		{
			PixlibDebug.DEBUG( "------------------------------------------" );
			
			_oB.setStep( 100 );
			var mc : MovieClip = new Animation2();
			var mcrt : MockMovieClipRT = new MockMovieClipRT ( mc, 40 );

			mcrt.start();
			_oB.onTick( null );
			
			assertEquals( mcrt + " failed to loop at the end of the animation", 1, mc.currentFrame );	
			
			mcrt.stop();
			
			PixlibDebug.DEBUG( "------------------------------------------" );
			
			var mc2 : MovieClip = new Animation2();
			var mcrt2 : MockMovieClipRT = new MockMovieClipRT ( mc2, 40, true, true );
			
			mcrt2.start();
			_oB.onTick( null );
			
			PixlibDebug.DEBUG( "------------------------------------------" );
			
			assertEquals( mcrt2 + " (reversed) failed to loop at the end of the animation", 2, mc2.currentFrame );	
		}
		
		public function testSetMovieClip () : void 
		{
			var m : MovieClip = new MovieClip ();
			_mcrt.setMovieClip( m );
			
			assertEquals ( _mcrt + ".setMovieClip() failed to add the new MovieClip", m, _mcrt.getMovieClip() );
			
			var errorOccurs : Boolean = false;
			try 
			{
				_mcrt.setMovieClip( null );
			}
			catch( e : Error )
			{
				errorOccurs = true;
			}
			assertTrue ( _mcrt + ".setMovieClip() don't failed when passing a null object", errorOccurs );
		}
		
		public function testSetFrameRate () : void 
		{
			_mcrt.setFramerate( 80 );
			
			assertEquals ( _mcrt + ".setFramerate() failed to set the new framerate", 80, _mcrt.getFramerate() );
		}
		
		public function testReverse () : void 
		{
			var a : Array = [6, 2, 6, 2, 6];
			var n : Number = 0;
			
			_oB.setStep( 100 );
			
			_mcrt.setLooping( false );
			_mcrt.gotoAndStop( 2 );
			_mcrt.start();
			
			while( n <= 4 ) 
			{
				_oB.onTick( null );
				assertEquals ( _mcrt + ".reverse() failed to change the way of the animation", a[n], _mc.currentFrame );
				_mcrt.reverse();
				n++;
			}
		}
		
		public function testReset () : void 
		{
			var a : Array = [5, 5, 5, 5, 5];
			var n : Number = 0;
			
			_oB.setStep( 100 );
			
			_mcrt.setLooping( false );
			_mcrt.start();
			
			while( n <= 4 ) 
			{
				_oB.onTick( null );
				assertEquals ( _mcrt + ".reset() failed to place the frame to start", a[n], _mc.currentFrame );
				_mcrt.reset();
				n++;
			}
		}
		
		public function testShowHide () : void 
		{
			assertTrue( _mc + ".visible isn't true at creation", _mc.visible );
			
			_mcrt.hide();
			
			assertFalse( _mc + ".visible isn't false after a hide call", _mc.visible );
			
			_mcrt.show();
			
			assertTrue( _mc + ".visible isn't true after a show call", _mc.visible );
		}
		
		
		public function testAsyncBehavior () : void 
		{
			var m : MockASyncCommandListener = new MockASyncCommandListener();
			
			_mcrt.setLooping( false );
			_mcrt.addASyncCommandListener( m );
			_mcrt.start();
			
			while( _mcrt.isRunning() ) 
			{
				_oB.onTick( null );
			}
			assertTrue ( _mcrt + " haven't dispatch the onCommandEnd event", m.called );
		}
		
		public function testGotoAndPlay () : void 
		{
			_mcrt.gotoAndPlay( 10 );
			assertTrue ( _mcrt + ".isRunning() return false after a gotoAndPlay() call", _mcrt.isRunning() );
			assertEquals ( _mcrt + ".gotoAndPlay() failed to move the playhead", 10, _mc.currentFrame );
			
			_mcrt.gotoAndPlay( "lastLabel" );
			assertTrue ( _mcrt + ".isRunning() return false after a second gotoAndPlay() call", _mcrt.isRunning() );
			assertEquals ( _mcrt + ".gotoAndPlay() failed to move the playhead to the label", 20, _mc.currentFrame );
			
			var b : Boolean;
			
			b = false;
			_mcrt.stop();
			try
			{
				_mcrt.gotoAndPlay( true );
			}
			catch( e : Error )
			{
				b = true;
			}
			assertTrue ( _mcrt + ".gotoAndPlay() don't failed with a boolean argument", b );
			
			b = false;
			_mcrt.stop();
			try
			{
				_mcrt.gotoAndPlay( 0.5 );
			}
			catch( e : Error )
			{
				b = true;
			}
			assertTrue ( _mcrt + ".gotoAndPlay() don't failed with a float argument", b );
			
			assertEquals ( _mcrt + ".gotoAndPlay() move the playhead while passing an invalid label", 20, _mc.currentFrame );
		}
		
		public function testGotoAndStop () : void 
		{
			_mcrt.start();
			
			_mcrt.gotoAndStop( 10 );
			assertFalse ( _mcrt + ".isRunning() return true after a gotoAndStop() call", _mcrt.isRunning() );
			assertEquals ( _mcrt + ".gotoAndStop() failed to move the playhead", 10, _mc.currentFrame );
			
			_mcrt.gotoAndStop( "lastLabel" );
			assertFalse ( _mcrt + ".isRunning() return false after a second gotoAndStop() call", _mcrt.isRunning() );
			assertEquals ( _mcrt + ".gotoAndStop() failed to move the playhead to the label", 20, _mc.currentFrame );
			
			var b : Boolean;
			
			b = false;
			_mcrt.start();
			try
			{
				_mcrt.gotoAndStop( true );
			}
			catch( e : Error )
			{
				b = true;
			}
			assertTrue ( _mcrt + ".gotoAndStop() don't failed with a boolean argument", b );
			
			b = false;
			_mcrt.start();
			try
			{
				_mcrt.gotoAndStop( 0.5 );
			}
			catch( e : Error )
			{
				b = true;
			}
			assertTrue ( _mcrt + ".gotoAndStop() don't failed with a float argument", b );
			
			assertEquals ( _mcrt + ".gotoAndStop() move the playhead while passing an invalid label", 20, _mc.currentFrame );
		}
		/*
		public function testGotoScene () : void 
		{
			var mc : MovieClip = new AnimationWithScene() as MovieClip;
			KairosDebug.DEBUG( "GOTO SCENE ------------------------------" );
			KairosDebug.DEBUG( mc );
			_mcrt.setMovieClip( mc );
			assertEquals ( _mcrt + ".setMovieClip() failed to switch on a movie containg scene", mc, _mcrt.getMovieClip() );
			assertEquals ( mc + ".currentScene don't return the right scene at creation", "SomeScene", mc.currentScene.name );
			
			_mcrt.gotoScene( "AnotherScene" );
			assertEquals ( _mcrt + ".gotoScene() failed to change the scene of the movie", "AnotherScene", mc.currentScene.name );
			
			_mcrt.gotoAndStop( 25 );
			assertEquals ( _mcrt + ".gotoAndStop() change the scene of the movie", "AnotherScene", mc.currentScene.name );
			assertEquals ( _mcrt + ".gotoAndStop() don't move the playhead", 25, _mc.currentFrame );
			
			_mcrt.gotoAndStop( "anotherLabelScene2" );
			assertEquals ( _mcrt + ".gotoAndStop() change the scene of the movie", "AnotherScene", mc.currentScene.name );
			assertEquals ( _mcrt + ".gotoAndStop() don't move the playhead with label", 31, _mc.currentFrame );
			assertEquals ( _mcrt + ".gotoAndStop() don't move the playhead with label", "anotherLabelScene2", _mc.currentLabel );
			
			KairosDebug.DEBUG( "GOTO SCENE ------------------------------" );
		} 
		*/
		public function testLocalSpeedGetterSetter () : void 
		{
			var errorOccurs : Boolean;
			
			errorOccurs = false;
			try
			{
				_mcrt.setLocalSpeed( 0 );
			}
			catch ( e : Error )
			{
				errorOccurs = true;
			}
			
			assertTrue( _mcrt + ".setLocalSpeed() don't failed with a value of 0", errorOccurs );
			assertEquals ( _mcrt + ".setLocalSpeed() with an invalid argument have modify the local speed", 1, _mcrt.getLocalSpeed() );
			
			errorOccurs = false;
			try
			{
				_mcrt.setLocalSpeed( -1 );
			}
			catch ( e : Error )
			{
				errorOccurs = true;
			}
			
			assertTrue( _mcrt + ".setLocalSpeed() don't failed with a negative value", errorOccurs );
			assertEquals ( _mcrt + ".setLocalSpeed() with an invalid argument have modify the local speed", 1, _mcrt.getLocalSpeed() );
			
			
			_mcrt.setLocalSpeed( 2 );
			assertEquals ( _mcrt + ".setLocalSpeed() failed to change the local speed", 2, _mcrt.getLocalSpeed() );
			
		}
		public function testTickBeaconGetterSetter () : void 
		{
			var errorOccurs : Boolean;
			
			errorOccurs = false;
			try
			{
				_mcrt.setTickBeacon( null );
			}
			catch ( e : Error )
			{
				errorOccurs = true;
			}
			
			assertTrue( _mcrt + ".setTickBeacon() don't failed with a null beacon", errorOccurs );
			
			var beacon : MockRTBeacon = new MockRTBeacon ();
			
			_mcrt.setTickBeacon( beacon );
			
			assertEquals ( _mcrt + ".setTickBeacon() failed to set the new beacon", beacon, _mcrt.getTickBeacon() );
		}
		public function testStartStop() : void
		{
			_mcrt.start ();
			
			_oB.onTick( null );
			assertTrue( _mcrt + ".isRunning() return false after a call of start", _mcrt.isRunning() );
			
			_mcrt.stop ();
			
			assertFalse( _mcrt + ".isRunning() return true after a call of sop", _mcrt.isRunning() );
		}
		
		public function testStartAlias () : void
		{
			_mcrt.execute ();
			assertTrue( _mcrt + ".isRunning() return false after a call of execute", _mcrt.isRunning() );
			_mcrt.stop ();
			
			_mcrt.play ();
			assertTrue( _mcrt + ".isRunning() return false after a call of play", _mcrt.isRunning() );
			_mcrt.stop ();
		}
	}
}